package com.peanut.devlibrary.media;

import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;

import com.tencent.mars.xlog.Log;

import java.io.IOException;

/**
 * Created by anonymouslystudio on 2017/6/26.
 */

public class AudioPlayer implements MediaPlayer.OnPreparedListener,
        MediaPlayer.OnErrorListener,
        MediaPlayer.OnCompletionListener {

    private static final String TAG = AudioPlayer.class.getSimpleName();
    private Context mCtx;
    private Uri mUri;

    private MediaPlayer mPlayer;

    private boolean mPrepared = false;
    private int mDuration = 0;

    private Thread mTimerThread;
    private Runnable mTimerRunnable;

    private Handler mHandler;

    private OnAudioPlayListener mListener;

    private static AudioPlayer _instance;

    private AudioPlayer() {

    }

    public static AudioPlayer getInstance() {
        if (_instance == null) {
            _instance = new AudioPlayer();
        }
        return _instance;
    }


    public void onDestory(){
        releasePlayer();
        _instance = null;
    }
    public void setOnAudioPlayListener(OnAudioPlayListener listener) {
        mListener = listener;
    }

    /**
     * 播放
     */
    public void play() {

        if (mUri == null) {
            Log.e(TAG, "audio uri is null, please set before use");
            if (mListener != null) {
                mListener.onError("audio uri is null, please set before use");
            }
            return;
        }
        if (mPlayer == null) {
            initialialPlay();
        }
        try {
            if (!mPrepared) {
                mPlayer.prepareAsync();
            } else {
                mPlayer.start();
            }
        } catch (IllegalStateException e) {
            Log.e(TAG, "play: " + e.toString());
            if (mListener != null) {
                mListener.onError("IllegalStateException " + e.toString());
            }
        }

    }

    /**
     * 暂停
     */
    public void pause() {
        if (mPlayer != null) {
            mPlayer.pause();
        }
    }

    /**
     * 设置播放的url和显示的View
     */
    public void setDataSource(Context ctx, Uri targetUri) {
        Log.d(TAG, "setDataSource: " + targetUri.toString() + " oldUri? " + (mUri == null ? "null" : mUri.toString()));
        if (mUri != null && mUri.toString().equals(targetUri.toString())) {
            Log.d(TAG, "same Uri return...");
            return;
        }
        Log.d(TAG, "新的文件，重置。。");
        if (mListener != null) {
            mListener.onReset();
        }
        releasePlayer();


        this.mCtx = ctx;
        this.mUri = targetUri;

        mPrepared = false;
        mDuration = 0;
        mHandler = new Handler(mCtx.getMainLooper());
    }

    public boolean isPlaying() {
        return (mPlayer != null && mPlayer.isPlaying());
    }

    private void initialialPlay() {
        Log.d(TAG, "initialize Player...");

        try {
            mPlayer = new MediaPlayer();
            mPlayer.setDataSource(mCtx, mUri);

            mPlayer.setOnPreparedListener(this);
            mPlayer.setOnErrorListener(this);
            mPlayer.setOnCompletionListener(this);
            mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            if (mListener != null) {
                mListener.onError("IllegalArgumentException " + e.toString());
            }
        } catch (SecurityException e) {
            e.printStackTrace();
            if (mListener != null) {
                mListener.onError("SecurityException " + e.toString());
            }
        } catch (IllegalStateException e) {
            e.printStackTrace();
            if (mListener != null) {
                mListener.onError("IllegalStateException " + e.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
            if (mListener != null) {
                mListener.onError("IOException " + e.toString());
            }
        }
    }


    private void startTimer() {
        Log.d(TAG, "startTimer");
        mTimerRunnable = new Runnable() {

            @Override
            public void run() {
                while (mPlayer != null) {
                    updateDisplayResources();
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                    }
                }
            }
        };
        mTimerThread = new Thread(mTimerRunnable);


        mTimerThread.start();
    }

    public void releasePlayer() {
        Log.d(TAG, "releasePlayer...");
        try {
            if (mPlayer != null) {
                if (mPlayer.isPlaying()) {
                    mPlayer.stop();
                }
                mPlayer.reset();
                mPlayer.release();

            }
        } catch (IllegalStateException e) {
            Log.w(TAG, "release player exception: " + e.toString());
            e.printStackTrace();
            if (mListener != null) {
                mListener.onError("IllegalStateException " + e.toString());
            }
        } finally {

            mPlayer = null;
            mDuration = 0;
            mPrepared = false;

            mTimerRunnable = null;
            mTimerThread = null;
            mListener = null;

        }


    }

    @Override
    public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
        if (mListener != null) {
            mListener.onError("数据源加载出错 " + arg1 + " " + arg2);
        }
        return false;
    }

    @Override
    public void onPrepared(MediaPlayer arg0) {
        Log.d(TAG,"onPrepared "+(mListener == null? "listener is null ":"listener is not null"));
        mPrepared = true;
        mDuration = mPlayer.getDuration();
        if (mListener != null) {
            mListener.onPrepared(mDuration);
        }
        updateDisplayResources();
        mPlayer.start();

        startTimer();
    }

    /**
     * 更新进度条和显示的时间
     */
    private void updateDisplayResources() {
        mHandler.post(new Runnable() {

            @Override
            public void run() {
                if (mPlayer != null) {
                    int currentPos = mPlayer.getCurrentPosition();
                    if (mListener != null) {
                        mListener.onPlay(currentPos);
                    }
                }

            }
        });

    }


    @Override
    public void onCompletion(MediaPlayer arg0) {
        mUri = null;
        if (mListener != null) {
            mListener.onComplete();
        }
        releasePlayer();

    }


    public Uri getCurrentUri() {
        return mUri;
    }

    public static String getPlayTimeStr(int seconds) {
        String displayMinute = "";
        String displaySecond = "";
        if (seconds < 60) {
            displayMinute = "00";
            if (seconds < 10) {
                displaySecond = "0" + seconds;
            } else {
                displaySecond = seconds + "";
            }
        } else {
            int minute = seconds / 60;
            int leftSecond = seconds - minute * 60;
            if (minute < 10) {
                displayMinute = "0" + minute;
            } else {
                displayMinute = minute + "";
            }

            if (leftSecond < 10) {
                displaySecond = "0" + leftSecond;
            } else {
                displaySecond = leftSecond + "";
            }
        }
        return displayMinute + ":" + displaySecond;
    }

    public interface OnAudioPlayListener {
        void onReset();

        void onError(String reason);

        void onPlay(long currentPos);

        void onComplete();

        void onPrepared(long totalTime);
    }
}
